#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

/**
 * ubuntu 22.04 下可以直接编译
 * 否则 gcc main.c -pthread
 * @return
 */
//int main() {
//    printf("Hello, World!\n");
//    pthread_t tid = 0;
//    //获取当前线程的线程号
//    tid = pthread_self();
//    printf("tid : %ld\n",tid);
//    // 判断两个线程是否相同
//    if(pthread_equal(tid,pthread_self())){
//        printf("thread = thread\n");
//    }
//    return 0;
//}

void * fun(void *arg){
    printf("new thread no arg %lu\n",pthread_self());
    return NULL;
}

void * fun1(void *arg){
    printf("new thread yes arg %lu\n",pthread_self());
    printf("arg %d\n",(int)(long)arg);
    return NULL;
}

/**
 * 创建线程
 *
 * @return
 */
//int main() {
//    pthread_t tid = 0;
//    pthread_t tid2 = 0;
//    int ret = -1;
//    // 创建无参线程
//    ret = pthread_create(&tid,NULL,fun,NULL);
//    if(ret != 0){
//        printf("create failed\n");
//        return 1;
//    }
//    // 创建有参线程
//    ret = pthread_create(&tid2,NULL,fun1,(void *)0x3);
//    if(ret != 0){
//        printf("create failed\n");
//        return 1;
//    }
//    printf("main : %lu\n",pthread_self());
//    printf("press anykey \n");
//    getchar();
//
//    return 0;
//}

int num = 100;
void* fun3(void *arg){
    int *pp = (int *) arg;
    printf("new thread num before %d\n",num);
    printf("new thread p before %d\n",*pp);
    num ++;
    (*pp)++;
    printf("new thread num after %d\n",num);
    printf("new thread p after %d\n",*pp);
    return NULL;
}

/**
 * 验证 数据段 和 堆 的共享
 * 线程共享的资源：
 *      文件描述符表
 *      每隔信号的处理方式
 *      当前工作目录
 *      用户ID和组ID
 *      内存地址空间
 *          text 代码段
 *          data 数据段
 *          bss  未初始化数据段
 *          heap 堆
 * 线程非共享的资源：
 *      线程id
 *      处理器线程和栈指针（内核栈）
 *      独立的栈空间（用户空间栈）
 *      errno变量
 *      信号屏蔽字
 *      调度优先级
 * @return
 */
//int main() {
//    pthread_t tid;
//    memset(&tid,0,sizeof(tid));
//
//    int * p = NULL;
//    p = malloc(sizeof(int));
//    memset(p,0, sizeof(int));
//    * p = 88;
//    int ret = -1;
//    ret = pthread_create(&tid,NULL,fun3,(void *)p);
//    printf("press anykey \n");
//    getchar();
//    printf("main thread num %d\n",num);
//    printf("main thread p %d\n",*p);
//
//
//    free(p);
//    p = NULL;
//    return 0;
//}
void * fun4(void *arg){

    printf("new thread n\n");
    sleep(3);
    return (void *) 0x3;
}
/**
 * 线程资源的回收
 * @return
 */
//int main(){
//    pthread_t tid;
//    void * retp = NULL;
//    int ret = -1;
//
//    memset(&tid,0,sizeof(tid));
//    ret = pthread_create(&tid,NULL,fun4,NULL);
//    printf("main run\n");
//    // 阻塞等待线程运行结束，并且获取线程的返回指针
//    ret = pthread_join(tid,retp);
//    printf("retp %p\n",retp);
//    printf("main exit\n");
//    return 0;
//}

void * fun5(void * arg){
    for(int c = 'A';c <= 'Z'; c++){
        putchar(c);
        fflush(stdout);
        usleep(100000);

    }
    return NULL;
}

void * fun6(void * arg){
    for(int c = 'a';c <= 'z'; c++){
        putchar(c);
        fflush(stdout);
        usleep(100000);

    }
    return NULL;
}

/**
 * 小练习
 * @return
 */
//int main(){
//    pthread_t tid1;
//    pthread_t tid2;
//
//    int ret = -1;
//
//    memset(&tid1,0,sizeof(tid1));
//    memset(&tid2,0,sizeof(tid2));
//    ret = pthread_create(&tid1,NULL,fun5,NULL);
//    ret = pthread_create(&tid2,NULL,fun6,NULL);
//    printf("main run\n");
//    // 阻塞等待线程运行结束，并且获取线程的返回指针
//    ret = pthread_join(tid1,NULL);
//    ret = pthread_join(tid2,NULL);
//    printf("\n");
//    printf("main exit\n");
//    return 0;
//}

void * fun7(void * arg){
    for (int i = 0; i < 5; ++i) {
        printf("thread running %d\n",i);
        sleep(1);
    }
    // 终止线程 等价于 return
    pthread_exit(NULL);
    //return NULL;
    //会退出整个进程
    //exit(0);
}

/**
 * 线程分离
 * 线程退出
 *      线程从执行函数退出
 *      线程调用 pthread_exit 函数退出
 *      线程可以被同一进程中的其他线程取消
 * @return
 */
//int main(){
//    pthread_t tid;
//    int ret = -1;
//    memset(&tid,0,sizeof(tid));
//
//    ret = pthread_create(&tid,NULL,fun7,NULL);
//
//    //设置线程分离
//    ret = pthread_detach(tid);
//
//    ret = pthread_join(tid,NULL);
//    if(ret != 0){
//        printf("分离出去的线程无法被join\n");
//    }
//    printf("main exit press anykey\n");
//    getchar();
//    return 0;
//}

/**
 * 线程分离
 * 线程退出
 *      线程从执行函数退出
 *      线程调用 pthread_exit 函数退出
 *      线程可以被同一进程中的其他线程取消
 * @return
 */
//int main(){
//    pthread_t tid;
//    int ret = -1;
//    memset(&tid,0,sizeof(tid));
//
//    ret = pthread_create(&tid,NULL,fun7,NULL);
//
//    //设置线程分离
//    ret = pthread_detach(tid);
//    sleep(2);
//    // 新线程被取消了
//    pthread_cancel(tid);
//    printf("main exit press anykey\n");
//    getchar();
//    return 0;
//}

/**
 * 线程属性
 * @return
 */
int main(){
    pthread_t tid;
    int ret = -1;
    pthread_attr_t attr;
    memset(&tid,0,sizeof(tid));
    // 初始化属性
    ret = pthread_attr_init(&attr);
    printf("线程属性初始化OK\n");

    // 设置属性，当前为设置分离线程
    ret = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

    // 创建线程，属性用定义的
    ret = pthread_create(&tid,&attr,fun7,NULL);

    // 用来判断是不是已经分离了
    ret = pthread_join(tid,NULL);
    if(ret != 0){
        printf("split \n");
    }

    // 销毁线程属性
    ret = pthread_attr_destroy(&attr);
    printf("线程属性初销毁OK\n");
    printf("main exit press anykey\n");
    getchar();
    return 0;
}